/*

Summary:
Window class.

Remark:
The root class of class hierarchy.

Version:
0.1.0

LastUpdatedDate:
2012-09-13

*/


#pragma once

#include <memory>
#include <string>
#include <Windows.h>
#include "Tool\Event.h"


namespace Zaf {
namespace Mwl {
namespace __Internal {
	class WindowState;
}


class Application;



struct EventArgs {
	EventArgs() : Sender(nullptr) { }
	virtual ~EventArgs() { }
	void* Sender;
};

struct CreatedEventArgs : public EventArgs {

};

struct DestroyedEventArgs : public EventArgs {

};



struct WndMsg {

	WndMsg() : Hwnd(0), Message(0), WParam(0), LParam(0) { }

	WndMsg(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
		: Hwnd(hwnd), Message(message), WParam(wParam), LParam(lParam) { }

	HWND Hwnd;
	UINT Message;
	union {
		struct {
			WORD WParamLow;
			WORD WParamHigh;
		};
		WPARAM WParam;
	};
	union {
		struct {
			WORD LParamLow;
			WORD LParamHigh;
		};
		LPARAM LParam;
	};
};



class Window {

public:
	virtual ~Window();

	void Create();

	bool IsEnable() const;
	void IsEnable(bool value);

	void GetSize(unsigned int& width, unsigned int& height);
	void SetSize(unsigned int width, unsigned int height);

	void GetPosition(unsigned int& x, unsigned int& y);
	void SetPosition(unsigned int x, unsigned int y);

	std::wstring GetText() const;
	void SetText(const wchar_t* value);
	void SetText(const std::wstring& value);

	void Redraw(bool erase = true);

	HWND GetHandle() const;

	Event<CreatedEventArgs&> CreatedEvent;
	Event<DestroyedEventArgs&> DestroyedEvent;

protected:
	Window();

	virtual LRESULT DefWndProc(const WndMsg& msg);
	virtual LRESULT WndProc(const WndMsg& msg);

	DWORD GetStyle() const;
	void SetStyle(DWORD value);

	DWORD GetExStyle() const;
	void SetExStyle(DWORD value);

	void ChangeStyle(DWORD style, bool enable);
	bool HasStyle(DWORD style) const;

	void ChangeExStyle(DWORD style, bool enable);
	bool HasExStyle(DWORD style) const;

	HWND GetParentOrOwner() const;
	void SetParentOrOwner(HWND value);

private:
	static LRESULT CALLBACK OriginalWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

	Window(const Window& rhs);
	const Window& operator=(const Window& rhs);

	virtual HWND CreateConcreteWindow() = 0;
	virtual LRESULT OnCommand(const WndMsg& msg);
	virtual LRESULT OnNotify(const WndMsg& msg);

	HWND m_hwnd;
	std::shared_ptr<__Internal::WindowState> m_state;
};


inline void Window::SetText(const std::wstring& value) {
	SetText(value.c_str());
}


inline HWND Window::GetHandle() const { return m_hwnd; }


}
}
